业务数据库设计 + CLI 生成模块代码
在完成角色权限、策略权限、菜单权限的设计之后,接下来的工作重心转向内容管理模块。内容管理的核心逻辑与菜单、角色、用户模块类似,差异主要体现在关联关系上——一对一、一对多、多对多的不同组合。本文将介绍如何复用已有数据库设计、完成内容模块的 Schema 定义,并借助 NestJS CLI 快速生成模块代码。
数据库设计流程
复用已有的 Migration
项目已经创建过 migration,可以直接在原有 schema.prisma 文件基础上追加修改:
# 1. 修改 schema.prisma,追加新的 model 定义
# 2. 使用 db push 推送到远端数据库,同时生成新的 Prisma Client
npx prisma db push
bash
db push 会完成两件事:
- 将 Schema 中的变更同步到远端数据库
- 在项目中重新生成 Prisma Client 类型定义
Schema 定义顺序
定义 Model 时应遵循以下顺序,避免外键依赖问题:
- 字典基础表(Dict)——
DictCourseTag、DictCourseType、DictAttachmentAttribute - 业务功能表 ——
Course、Content、Comment、Attachment - 关联表 ——
CourseTag、ContentAttachment、ContentTag、CourseComment、ContentComment
完成后的数据库结构包含约 25 张表:
| 分类 | 表名 | 说明 |
|---|---|---|
| 业务主表 | Course | 课程 |
| 业务主表 | Content | 内容 |
| 业务主表 | Comment | 评论 |
| 业务主表 | Attachment | 附件 |
| 关联表 | CourseTag | 课程标签关联 |
| 关联表 | ContentTag | 内容标签关联 |
| 关联表 | ContentAttachment | 内容附件关联 |
| 关联表 | CourseComment | 课程评论 |
| 关联表 | ContentComment | 内容评论 |
| 关联表 | AttachmentAttribute | 附件属性值 |
| 字典表 | DictCourseTag | 课程标签字典 |
| 字典表 | DictCourseType | 课程分类字典 |
| 字典表 | DictAttachmentAttribute | 附件属性字典 |
Prisma 多 Schema 方案(进阶)
Prisma 官方不支持多文件 Schema 模式,但社区有第三方包 prisma-multi-schema 可按功能模块拆分 Schema 文件。
使用方式:
# 按模块创建子 Schema
sub-schema/
├── user.schema.prisma
├── course.schema.prisma
└── content.schema.prisma
# 合并为单一 schema.prisma
npx prisma-multi-schema
bash
注意事项: 在使用 VS Code 的 Prisma 官方插件时,跨文件定义的关联关系无法被插件正确识别——保存时不会自动生成关联属性项。因此,在项目初期建议将所有关联 Model 定义在同一个 schema.prisma 文件中,避免插件无法正确解析 @relation 导致的类型丢失问题。
NestJS CLI 快速生成模块
核心命令
NestJS CLI 提供了多种生成器,可快速创建模块骨架代码:
# 生成完整的 CRUD 资源(Controller + Service + Module + DTO)
nest g resource modules/course
# 仅生成 Module
nest g module modules/dict
# 生成前预览(不实际创建文件)
nest g resource modules/course --dry-run
bash
| 命令别名 | 生成内容 |
|---|---|
nest g resource <name> | 完整 CRUD 骨架(Controller + Service + Module + DTO) |
nest g module <name> | 仅 Module 文件 |
nest g controller <name> | Controller + Module |
nest g service <name> | Service + Module |
实际生成流程
以内容管理模块为例,按以下顺序执行:
# 1. 主业务模块(完整 CRUD 资源)
nest g resource modules/course
nest g resource modules/content
nest g resource modules/comment
nest g resource modules/attachment
# 2. 字典模块(仅 Module)
nest g module modules/dict
# 3. 字片子模块(完整 CRUD,注册到 dict 目录下)
nest g resource modules/dict/attachment-attribute
nest g resource modules/dict/course-tag
nest g resource modules/dict/course-type
bash
nest g resource 会自动更新根模块的 imports 数组,无需手动在 app.module.ts 中导入。生成的目录结构如下:
src/modules/
├── course/
│ ├── course.module.ts
│ ├── course.controller.ts
│ ├── course.controller.spec.ts
│ ├── course.service.ts
│ └── dto/
│ ├── create-course.dto.ts
│ └── update-course.dto.ts
├── content/
│ └── ...
├── comment/
│ └── ...
├── attachment/
│ └── ...
└── dict/
├── dict.module.ts
├── attachment-attribute/
│ ├── attachment-attribute.module.ts
│ ├── attachment-attribute.controller.ts
│ ├── attachment-attribute.service.ts
│ └── dto/
├── course-tag/
│ └── ...
└── course-type/
└── ...
text
Controller 路径调整
字典子模块生成后,需要将 Controller 的路由前缀调整到 dict/ 下:
// attachment-attribute.controller.ts
@Controller('dict/attachment-attribute')
export class AttachmentAttributeController {
// ...
}
// course-tag.controller.ts
@Controller('dict/course-tag')
export class CourseTagController {
// ...
}
// course-type.controller.ts
@Controller('dict/course-type')
export class CourseTypeController {
// ...
}
typescript
小结
| 步骤 | 命令/操作 | 耗时 |
|---|---|---|
| 定义 Schema | 编辑 schema.prisma | 视业务复杂度 |
| 推送到数据库 | npx prisma db push | 几秒 |
| 生成模块代码 | nest g resource / nest g module | 约 3 分钟 |
| 调整路由 | 修改 Controller 装饰器 | 约 1 分钟 |
借助 NestJS CLI,整个业务模块的骨架代码生成不超过 5 分钟。后续开发基础属性的 CRUD 接口时,配合 AI 工具(如 Cursor、Cline)可进一步提升效率。
↑